/**
 * @file SystemeDeVersionnageTest.cpp
 * @author Pierre Le Bodic
 * @date Mardi 27 décembre 2011
 */

#include "gtest.h"
#include <vector>
#include "SystemeDeVersionnage.h"
#include "SystemeDeVersionnageTest.h"

namespace gestionnaireDeVersions {
   using std::vector;

//On vérifie (autant que possible) ici que dans les classes filles, les 
//attributs de la classe mère ont été initialisés correctement.
TEST_P(SystemeDeVersionnageTest, initialisationConforme) {
   //On veut au moins 5 exemples différents de chaque type:
   ASSERT_TRUE(GetParam()->nbChainesNonValides()>=5);
   ASSERT_TRUE(GetParam()->nbChainesValides()>=5);
   
   //On veut au moins 5 exemples de chaînes croissantes:
   ASSERT_TRUE(GetParam()->nbChainesCroissantes()>=5);
   
   //On veut que le systeme soit initialisé
   ASSERT_FALSE(GetParam()->getSystemeDeVersionnage()==NULL);
}

TEST_P(SystemeDeVersionnageTest,estValide) {
   unsigned int i;
   
   //test du cas non valide:
   for(i=0;i<GetParam()->nbChainesNonValides();i++) {
      ASSERT_FALSE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineNonValide(i)));
   }
   
   //test du cas valide:
   for(i=0;i<GetParam()->nbChainesValides();i++) {
      ASSERT_TRUE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineValide(i)));
   }
   
}

TEST_P(SystemeDeVersionnageTest,getNom) {
   ASSERT_FALSE(GetParam()->getSystemeDeVersionnage()->getNom()=="");
}


TEST_P(SystemeDeVersionnageTest, comparestring) {
   //On vérifie que les exceptions soient bien lancées dans tous les cas:
     
   //On vérifie qu'il en existe au moins un exemple:
   ASSERT_TRUE(GetParam()->nbChainesNonValides()>=1);
   ASSERT_TRUE(GetParam()->nbChainesValides()>=1);
   
   //et que l'exemple est bien un exemple du bon cas (valide ou non valide)
   ASSERT_FALSE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineNonValide(0)));
   ASSERT_TRUE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineValide(0)));
   
   //On définit une Version valide et une non valide:
   string versionValide(GetParam()->getChaineValide(0)),
       versionNonValide(GetParam()->getChaineNonValide(0));
   
   //On vérifie:
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(versionValide,versionNonValide),ExceptionDeVersion);
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(versionNonValide,versionValide),ExceptionDeVersion);
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(versionNonValide,versionNonValide),ExceptionDeVersion);
   ASSERT_NO_THROW(GetParam()->getSystemeDeVersionnage()->compare(versionValide,versionValide));
   
   //On vérifie que les comparaisons se passent bien:
   //On parcourt dans un sens puis dans l'autre, puis on vérifie chaque
   //élément avec lui-même
   unsigned int i;
   //deux sens:
   for(i=1;i<GetParam()->nbChainesCroissantes();i++) {
      //On vérifie (en mettant les paramètres dans les deux sens possibles) que la comparaison se passe bien:
      ASSERT_EQ(-1,GetParam()->getSystemeDeVersionnage()->compare(GetParam()->getChaineCroissante(i-1),GetParam()->getChaineCroissante(i)));
      ASSERT_EQ(1,GetParam()->getSystemeDeVersionnage()->compare(GetParam()->getChaineCroissante(i),GetParam()->getChaineCroissante(i-1)));
   }   
   //comparaison avec soi:
   for(i=0;i<GetParam()->nbChainesCroissantes();i++) {
      ASSERT_EQ(0,GetParam()->getSystemeDeVersionnage()->compare(GetParam()->getChaineCroissante(i),GetParam()->getChaineCroissante(i)));
   }
   
}

TEST_P(SystemeDeVersionnageTest, compareVersion) {
   //On vérifie que les exceptions soient bien lancées dans tous les cas:
   
   //On définit une Version valide et une non valide:
   Version versionValide, versionNonValide;
   
   //On vérifie qu'il en existe au moins un exemple:
   ASSERT_TRUE(GetParam()->nbChainesNonValides()>=1);
   ASSERT_TRUE(GetParam()->nbChainesValides()>=1);
   
   //et que l'exemple est bien un exemple du bon cas (valide ou non valide)
   ASSERT_FALSE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineNonValide(0)));
   ASSERT_TRUE(GetParam()->getSystemeDeVersionnage()->estValide(GetParam()->getChaineValide(0)));
   
   //On peut alors affecter les valeurs
   versionValide.setChaineVersion(GetParam()->getChaineValide(0));
   versionNonValide.setChaineVersion(GetParam()->getChaineNonValide(0));
   
   //On vérifie enfin:
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(&versionValide,&versionNonValide),ExceptionDeVersion);
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(&versionNonValide,&versionValide),ExceptionDeVersion);
   ASSERT_THROW(GetParam()->getSystemeDeVersionnage()->compare(&versionNonValide,&versionNonValide),ExceptionDeVersion);
   ASSERT_NO_THROW(GetParam()->getSystemeDeVersionnage()->compare(&versionValide,&versionValide));
   
   //On vérifie que les comparaisons se passent bien:
   //On parcourt dans un sens puis dans l'autre, puis on vérifie chaque
   //élément avec lui-même
   unsigned int i;
   //On crée un vecteur de Version à partir des chaînes:
   vector<Version> versionsCroissantes;
   for(i=0;i<GetParam()->nbChainesCroissantes();i++) {
      ASSERT_NO_THROW(versionsCroissantes.push_back(
      Version(GetParam()->getSystemeDeVersionnage(), GetParam()->getChaineCroissante(i))
      ));
   }
   
   //On fait les mêmes vérifs que dans le cas des chaînes.

   //deux sens:
   for(i=1;i<versionsCroissantes.size();i++) {
      //On vérifie (en mettant les paramètres dans les deux sens possibles) que la comparaison se passe bien:
      ASSERT_EQ(-1,GetParam()->getSystemeDeVersionnage()->compare(&versionsCroissantes.at(i-1),&versionsCroissantes.at(i)));
      ASSERT_EQ(1,GetParam()->getSystemeDeVersionnage()->compare(&versionsCroissantes.at(i),&versionsCroissantes.at(i-1)));
   }
   
   //comparaison avec soi:
   for(i=0;i<versionsCroissantes.size();i++) {
      ASSERT_EQ(0,GetParam()->getSystemeDeVersionnage()->compare(&versionsCroissantes.at(i),&versionsCroissantes.at(i)));
   }
}


}//namespace
